package com.hopes.bizz.close.statistic.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hopes.bizz.close.common.constant.ParkCloseProperty;
import com.hopes.bizz.close.common.constant.enums.ParkCloseSysDictEnum;
import com.hopes.bizz.close.hazard.entity.ClosedAlarmHazardCarEntity;
import com.hopes.bizz.close.hazard.service.ClosedAlarmHazardCarService;
import com.hopes.bizz.close.statistic.dto.AlarmChartDTO;
import com.hopes.bizz.close.statistic.service.ClosedAlarmStatisticService;
import com.hopes.bizz.close.statistic.vo.AlarmChartVO;
import com.hopes.bizz.close.statistic.vo.TypeNumVO;
import com.hopes.bizz.common.core.constant.CommonEnum;
import com.hopes.bizz.common.core.util.DateUtils;
import com.hopes.boss.admin.api.resolver.DictResolver;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author yumr
 * @ProjectName bizz
 * @Description 危险品车辆报警统计
 * @time 2024/2/11 22:30
 */
@Service
@RequiredArgsConstructor
public class ClosedAlarmStatisticServiceImpl implements ClosedAlarmStatisticService {

    private final ParkCloseProperty parkCloseProperty;
    private final ClosedAlarmHazardCarService closedAlarmHazardCarService;

    @Override
    public List<AlarmChartVO> queryAlarmChart(Integer alarmType, String beginTimeStr, String endTimeStr) {
        final Date endTime = DateUtils.parseDate(CommonEnum.StartEndEnum.END, endTimeStr);
        final Date beginTime = DateUtils.parseDate(CommonEnum.StartEndEnum.START, beginTimeStr);
        int calendar = Calendar.HOUR_OF_DAY;
        Function<Date, String> timeHandleMapper = DateUtils::limitHour;
        if (DateUtils.getIntervalDays(beginTime, endTime) > parkCloseProperty.getGis().getChartHourToDay()) {
            calendar = Calendar.DAY_OF_YEAR;
            timeHandleMapper = DateUtils::limitDay;
        }
        final List<AlarmChartVO> result = new ArrayList<>();

        final List<String> indexList = handlerDateTime(beginTime, endTime, timeHandleMapper, calendar, 1);
        // 1、查询报警类型
        final LambdaQueryWrapper<ClosedAlarmHazardCarEntity> queryWrapper = Wrappers.<ClosedAlarmHazardCarEntity>lambdaQuery()
                .gt(ClosedAlarmHazardCarEntity::getAlarmTime, beginTime)
                .lt(ClosedAlarmHazardCarEntity::getAlarmTime, endTime)
                .eq(ObjUtil.isNotNull(alarmType), ClosedAlarmHazardCarEntity::getAlarmType, alarmType);
        final List<ClosedAlarmHazardCarEntity> closedAlarmHazardCarList = closedAlarmHazardCarService.list(queryWrapper);
        final List<Integer> alarmTypeList = closedAlarmHazardCarList.stream().map(ClosedAlarmHazardCarEntity::getAlarmType).filter(ObjUtil::isNotNull).collect(Collectors.toList());
        for (String index : indexList) {
            result.add(new AlarmChartVO(index, buildTypeNumList(index, alarmTypeList, closedAlarmHazardCarList, timeHandleMapper)));
        }
        return result;
    }

    private List<TypeNumVO> buildTypeNumList(String index, List<Integer> alarmTypeList, List<ClosedAlarmHazardCarEntity> recordList, Function<Date, String> timeHandleMapper) {
        if (CollUtil.isEmpty(alarmTypeList)) {
            return new ArrayList<>();
        }
        final List<TypeNumVO> typeNumVOList = new ArrayList<>(alarmTypeList.size());
        if (CollUtil.isEmpty(recordList)) {
            for (Integer alarmType : alarmTypeList) {
                typeNumVOList.add(new TypeNumVO(alarmType.toString(), DictResolver.getItemLabelByValue(ParkCloseSysDictEnum.close_hazard_alarm_type, alarmType), 0));
            }
            return typeNumVOList;
        }

        for (Integer alarmType : alarmTypeList) {
            final long count = recordList.parallelStream().filter(e -> ObjUtil.isNotNull(e.getAlarmTime()) && ObjUtil.isNotNull(e.getAlarmType()))
                    .filter(e -> timeHandleMapper.apply(e.getAlarmTime()).equals(index) && e.getAlarmType().equals(alarmType)).count();
            typeNumVOList.add(new TypeNumVO(alarmType.toString(), DictResolver.getItemLabelByValue(ParkCloseSysDictEnum.close_hazard_alarm_type, alarmType), Long.valueOf(count).intValue()));
        }
        return typeNumVOList;
    }

    /**
     * 处理时间
     *
     * @param beginTime 开始时间
     * @param endTime   结束时间
     * @param mapper    函数，格式化时间
     * @param calendar  类型 如: Calendar.DAY_OF_YEAR, Calendar.HOUR_OF_DAY 等
     * @param step      步长
     * @return 结果
     */
    private List<String> handlerDateTime(Date beginTime, Date endTime, Function<Date, String> mapper, Integer calendar, Integer step) {
        final List<String> list = new ArrayList<>();
        final Calendar instance = Calendar.getInstance();
        instance.setTime(beginTime);
        while (instance.getTimeInMillis() < endTime.getTime()) {
            final String apply = mapper.apply(instance.getTime());
            list.add(apply);
            instance.add(calendar, step);
        }
        return list;
    }
}
